//
//  TWWebClient.m
//  TWHomework-WeChat
//
//  Created by wzb on 2019/11/12.
//  Copyright © 2019 WZB. All rights reserved.
//

#import "TWWebClient.h"
#import "TWBaseReponseModel.h"
#import "TWBaseRequestModel.h"
#import <YYModel.h>
#import "Define.h"
#import <AFImageDownloader.h>

/**
*  错误代码
*/
static NSString *const kNoNewWork = @"当前设备无网络";

static NSInteger const kErrorCodeNoNetwork = 11001;

/**
* 网络状态
*/
static AFNetworkReachabilityStatus networkStatus = 1;

@implementation TWWebClient

#pragma mark - public
+ (TWWebClient *)sharedClient {
    static TWWebClient *_sharedClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
          _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:TWWebClient.__getBaseUrl]];
          _sharedClient.requestSerializer = [AFJSONRequestSerializer serializer];
          [_sharedClient.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
          _sharedClient.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingMutableContainers];
          _sharedClient.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"sparql-results+json", @"text/json", @"text/html",@"text/plain", @"text/xml",@"text/text", nil];
        [self __startMonitoringNetworkStatus];
    });
    return _sharedClient;
}

- (NSURLSessionDataTask *)request:(TWBaseRequestModel *)request success:(void (^)(TWBaseReponseModel *response))success failure:(void (^)(NSURLSessionDataTask *operation, NSError *e))failure {
    
    // 检查网络状态
    if (networkStatus == AFNetworkReachabilityStatusNotReachable) {
        if (failure != nil) {
            failure(nil, [[NSError alloc] initWithDomain:TWWebClient.__getBaseUrl code:kErrorCodeNoNetwork userInfo:@{NSLocalizedDescriptionKey: kNoNewWork}]);
        }
        return nil;
    }

    //获取请求参数
    NSMutableDictionary* parameters = [self __getParamsByRequest:request];
    NSString* path = parameters[REQUEST_PAHT];
    
    // 定义回调处理
    void (^successBlocker)(NSURLSessionDataTask * _Nonnull, id _Nullable) = ^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject){
        NSLog(@"[<= %@]data:%@ ", task.currentRequest, responseObject);
        TWBaseReponseModel *model = [[TWBaseReponseModel alloc] init];
        model.response = responseObject;
        if (success) {
            success(model);
        }
    };

    void (^failureBlocker)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull) = ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error){
        NSLog(@"[<= %@]fail:%@", task.currentRequest, error.localizedDescription);
        if (failure) {
            NSLog(@"%@",error.userInfo);
            failure((NSURLSessionDataTask *)task, error);
        }
    };
    //清理多余参数
    TWRequestModel request_model = [parameters[REQUEST_MODEL] intValue];
    id request_caller = parameters[REQUEST_CALLER];
    [parameters removeObjectsForKeys:@[REQUEST_MODEL, REQUEST_CALLER, REQUEST_PAHT, @"caller", @"model", @"apiUrl"]];
    
    NSString *url = [NSString stringWithFormat:@"%@%@", TWWebClient.__getBaseUrl, path];
    [self.requestSerializer setTimeoutInterval:30];
    self.requestSerializer.HTTPShouldHandleCookies = NO;
    
    // 发起请求
    NSURLSessionDataTask *task = nil;
    if (request_model == TWRequestModelGet) {
        task = [self GET:url parameters:parameters progress:nil success:successBlocker failure:failureBlocker];
    } else if (request_model == TWRequestModelPost) {
        NSLog(@"parameters -- %@", parameters);
        self.requestSerializer = [AFHTTPRequestSerializer serializer];
        [self.requestSerializer setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
        task = [self POST:url parameters:parameters progress:nil success:successBlocker  failure:failureBlocker];
    }
    
    // 向ViewModel注册请求
    SEL registerRequest = NSSelectorFromString(@"registerRequest:");
    if (request_caller && [request_caller respondsToSelector:registerRequest]) {
        IMP imp = [request_caller methodForSelector:registerRequest];
        void (*func)(id, SEL, id) = (void *)imp;
        func(request_caller, registerRequest, task);
    }
    return task;
}

- (void)removeAllOperation {
    [self.operationQueue cancelAllOperations];
}

- (void)removeOperation:(NSURLSessionDataTask *)operation {
    [operation cancel];
}

#pragma mark - private
- (NSMutableDictionary *)__getParamsByRequest:(TWBaseRequestModel *)request {
    NSMutableDictionary* parameters = [[NSMutableDictionary alloc] initWithDictionary:[request getParameterDictionary]];
    parameters[REQUEST_PAHT] = request.apiUrl;
    parameters[REQUEST_CALLER] = request.caller;
    parameters[REQUEST_MODEL] = @(request.model);
    return parameters;
}

+ (void)__startMonitoringNetworkStatus
{
    AFNetworkReachabilityManager *networkManager = [AFNetworkReachabilityManager sharedManager];
    [networkManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        networkStatus = status;
        switch (status) {
            case AFNetworkReachabilityStatusUnknown:
                break;
            case AFNetworkReachabilityStatusNotReachable: {
                NSLog(@"当前设备无网络");
            }
                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:
                NSLog(@"当前Wi-Fi网络");
                break;
            case AFNetworkReachabilityStatusReachableViaWWAN:
                NSLog(@"当前蜂窝移动网络");
                break;
            default:
                break;
        }
    }];
    [networkManager startMonitoring];
}

+ (NSString *)__getBaseUrl
{
    return KServer_baseURL;
}

- (void)downloadImage:(NSString *)url success:(void(^)(UIImage *image))success failure:(void(^)(NSError * _Nonnull error))failure
{
    NSURL *URL = [NSURL URLWithString:url];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
    AFImageDownloader *downloader = [AFImageDownloader defaultInstance];
    [downloader downloadImageForURLRequest:request success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull responseObject) {
        if (success) {
            success(responseObject);
        }
    } failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {
        if (failure) {
            failure(error);
        }
    }];
}

@end
